﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

namespace gt.framework.Utils
{
    public static class EnumUtils
    {
        public static string GetEnumValueName(Enum instance)
        {
            return instance.ToString();
        }

        public static T GetEnumItem<T>(string enumNameOrValue) where T : struct
        {
            return (T)Enum.Parse(typeof(T), enumNameOrValue, true);
        }


        /// <summary>
        /// get the enum's all list
        /// </summary>
        /// <param name="enumType">枚举的类型</param>
        /// <returns></returns>
        public static List<EnumItem> GetEnumItems(Type enumType)
        {
            return GetEnumItems(enumType, false);
        }

        /// <summary>
        /// 获得枚举类型所包含的全部项的列表，包含"All"。
        /// </summary>
        /// <param name="enumType">the type of the enum</param>
        /// <returns></returns>
        public static List<EnumItem> GetEnumItemsWithAll(Type enumType)
        {
            return GetEnumItems(enumType, true);
        }

        /// <summary>
        /// 通过枚举类型的值获取该枚举项的描述
        /// </summary>
        /// <param name="enumType"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetEnumItemDescription(Type enumType, int value)
        {
            var list = GetEnumItems(enumType);

            if (list != null && list.Count > 0)
            {
                return list.Find(i => int.Parse(i.Key.ToString()) == value).Value.ToString();
            }

            return string.Empty;
        }
        public static string GetEnumItemDescription<T>(int value)
        {
            return GetEnumItemDescription(typeof(T), value);
        }

        /// <summary>
        /// get the enum's all list
        /// </summary>
        /// <param name="enumType">the type of the enum</param>
        /// <param name="withAll">identicate whether the returned list should contain the all item</param>
        /// <returns></returns>
        public static List<EnumItem> GetEnumItems(Type enumType, bool withAll)
        {
            List<EnumItem> list = new List<EnumItem>();

            if (enumType.IsEnum != true)
            {
                // just whethe the type is enum type
                throw new InvalidOperationException();
            }

            if (withAll == true)
            {
                list.Add(new EnumItem(-1, "All"));
            }

            // 获得特性Description的类型信息
            Type typeDescription = typeof(DescriptionAttribute);

            // 获得枚举的字段信息（因为枚举的值实际上是一个static的字段的值）
            FieldInfo[] fields = enumType.GetFields();

            // 检索所有字段
            foreach (FieldInfo field in fields)
            {
                // 过滤掉一个不是枚举值的，记录的是枚举的源类型
                if (field.FieldType.IsEnum == false)
                {
                    continue;
                }

                // 通过字段的名字得到枚举的值
                int value = (int)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null);
                string text = string.Empty;

                // 获得这个字段的所有自定义特性，这里只查找Description特性
                object[] arr = field.GetCustomAttributes(typeDescription, true);
                if (arr.Length > 0)
                {
                    // 因为Description自定义特性不允许重复，所以只取第一个
                    DescriptionAttribute description = (DescriptionAttribute)arr[0];

                    // 获得特性的描述值
                    text = description.Description;
                }
                else
                {
                    // 如果没有特性描述，那么就显示英文的字段名
                    text = field.Name;
                }
                list.Add(new EnumItem(value, text));
            }

            return list;
        }

        /// <summary>
        /// get the enum value's int mode value
        /// </summary>
        /// <typeparam name="T">the type of the enum</typeparam>
        /// <param name="description">the enum value</param>
        /// <returns></returns>
        public static int GetEnumKeyByDescription<T>(string description)
        {
            if (string.IsNullOrEmpty(description))
            {
                return -1;
            }

            Type enumType = typeof(T);
            List<EnumItem> list = GetEnumItems(enumType);
            foreach (EnumItem item in list)
            {
                if (item.Value.ToString().ToLower() == description.Trim().ToLower())
                {
                    return Convert.ToInt32(item.Key);
                }
            }
            return -1;
        }

        /// <summary>
        /// get the Enum value according to the its decription
        /// </summary>
        /// <typeparam name="T">the type of the enum</typeparam>
        /// <param name="description">the description of the EnumValue</param>
        /// <returns></returns>
        public static T GetEnumByDescription<T>(string description)
        {
            if (string.IsNullOrEmpty(description))
            {
                return default(T);
            }

            Type enumType = typeof(T);
            List<EnumItem> list = GetEnumItems(enumType);
            foreach (EnumItem item in list)
            {
                if (item.Value.ToString().ToLower() == description.Trim().ToLower())
                {
                    return (T)item.Key;
                }
            }
            return default(T);
        }

        /// <summary>
        /// 根据枚举的值，获取枚举
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static T GetEnumByKey<T>(object key)
        {
            if (key == null)
            {
                return default(T);
            }

            try
            {
                Type enumType = typeof(T);
                List<EnumItem> list = GetEnumItems(enumType);
                foreach (EnumItem item in list)
                {
                    if (item.Key.ToString().Trim().ToLower() == key.ToString().Trim().ToLower())
                    {
                        return (T)item.Key;
                    }
                }
                return default(T);
            }
            catch
            {
                return default(T);
            }
        }
    }

    /// <summary>
    /// RelationShip between Key and Value
    /// Key是枚举类型的Value，Value是枚举类型的描述
    /// </summary>
    public class EnumItem
    {
        private object key;
        private object value;

        /// <summary>
        /// Enum Key
        /// </summary>
        public object Key
        {
            get
            {
                return this.key;
            }
        }

        /// <summary>
        /// Enum Value
        /// </summary>
        public object Value
        {
            get
            {
                return this.value;
            }
        }

        /// <summary>
        /// Custructor
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public EnumItem(object key, object value)
        {
            this.key = key;
            this.value = value;
        }
    }
}
